package com.omronble.bp_broadcast;

import android.annotation.SuppressLint;
import android.app.KeyguardManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.Nullable;
import okhttp3.Call;
import okhttp3.MediaType;

import com.google.gson.Gson;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechEvent;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.util.ResourceUtil;
import com.omron.lib.OMRONLib;
import com.omron.lib.common.OMRONBLEErrMsg;
import com.omron.lib.device.DeviceType;
import com.omron.lib.model.BPData;
import com.omronble.bp_broadcast.bean.BpBean;
import com.omronble.bp_broadcast.bean.XBpData;
import com.omronble.bp_broadcast.tools.Constants;
import com.omronble.bp_broadcast.tools.Utils;
import com.zhy.http.okhttp.OkHttpUtils;
import com.zhy.http.okhttp.callback.StringCallback;

import org.json.JSONException;
import org.json.JSONObject;
import org.litepal.crud.DataSupport;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

public class XService extends Service implements Runnable {
    private Thread thread ;
    private SpeechSynthesizer mTts;
    private String TAG = getClass().getSimpleName();
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private SharedPreferences mSharedPreferences ;
    private int time = 0 ;
    private boolean isGetData;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        return super.onUnbind(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        isGetData = true ;
        initSpeecher();
        thread = new Thread(this);
        thread.start();
    }



    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if ( thread.isInterrupted() ) {
            thread = new Thread(this);
            thread.start();
        }
        if ( null == mTts )
            initSpeecher();
        return Service.START_STICKY;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(10000);

               /* try {
                    wakeUpAndUnlock();
                    boolean enable = mSharedPreferences.getBoolean(Constants.VOICE_ENABLE,true);
                    if ( enable ) {
                        initParams();
                        int code = mTts.startSpeaking("您的血压数据为", mTtsListener);
                        Thread.sleep(3000);
                        code = mTts.startSpeaking("高压:123", mTtsListener);
                        Thread.sleep(3000);
                        code = mTts.startSpeaking("低压:64", mTtsListener);
                        Thread.sleep(3000);
                        code = mTts.startSpeaking("脉搏:90", mTtsListener);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
                
                time ++ ;
                isGetData = Utils.getIsGetBpData(this);
                String deviceId = mSharedPreferences.getString(Constants.deviceId,null);
                String deviceMac = mSharedPreferences.getString(Constants.deviceMac,null);
                Log.d(TAG,"Time=" + time + ";deviceId=" + deviceId + ";deviceMac=" + deviceMac+ ";isGetData=" + isGetData ) ;
                if ( null != deviceId && null != deviceMac &&isGetData ) {
                    Log.d("OMRONLib>>>","getDeviceData>>Start>>>" + sdf.format(new Date()) );
                    DeviceType deviceType = Constants.mDeviceType;
                    OMRONLib.getInstance().getDeviceData(this, deviceType, deviceId, myOmronBleCallBack,deviceMac);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    /*********************************欧姆龙*************************************/
    private OMRONLib.OmronBleCallBack myOmronBleCallBack = new OMRONLib.OmronBleCallBack() {
        @Override
        public void onFailure(OMRONBLEErrMsg omronbleErrMsg) {
            Log.d("OMRONLib>>>","getDeviceData>>End>>>" + sdf.format(new Date()) );
            if ( null != omronbleErrMsg )
                Log.e(TAG,omronbleErrMsg.getErrCode() + ":" + omronbleErrMsg.getErrMsg() );
        }

        @Override
        public void onBindComplete(String s, String s1, String s2) {

        }

        @Override
        public void onDataReadComplete(List<BPData> list) {
            
            if ( mTts == null )
                return;
            if ( null != list && list.size() > 0 ) {
                BPData data = list.get(0);
                bpDataConvertSave(data);
                try {
                    wakeUpAndUnlock();
                    initParams();
                    boolean enable = mSharedPreferences.getBoolean(Constants.VOICE_ENABLE,true);
                    if ( enable ) {
                        int code = mTts.startSpeaking("您的血压数据为", mTtsListener);
                        speak("高压:" + data.getSystolic(),3000);
                        speak("低压:" + data.getDiastolic(),6000);
                        speak("脉搏：" + data.getPulse(),9000);
                    }
                    sendDataToServer(data);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };

    private void speak(String speakString,long delayMillis){
        new Handler().postDelayed(() -> {
            initParams();
            mTts.startSpeaking(speakString, mTtsListener);
            }, delayMillis);
    }


    private void sendDataToServer(BPData data){
        BpBean bpBean = new BpBean();
        bpBean.setDevice_ble_cmn_id( mSharedPreferences.getString( Constants.deviceName ,null ) );
        bpBean.setSbp( data.getSystolic() );
        bpBean.setDbp( data.getDiastolic() );
        bpBean.setPulse( data.getPulse() );
        float lng = mSharedPreferences.getFloat( "Longitude" ,0f );
        bpBean.setLng( lng );
        float lat = mSharedPreferences.getFloat( "Latitude" ,0f );
        bpBean.setLat( lat );
        bpBean.setMeasure_at( ""+data.getMeasureTime() );
        bpBean.setSignature( md5Decode32(bpBean.getMeasure_at()+ Constants.MD5KEY) );
        bpBean.save();

        saveBpList();
    }


    private void saveBpList() {
        List<BpBean> list = DataSupport.findAll(BpBean.class);
        for (BpBean bean: list) {
            String json = new Gson().toJson(bean);
            String json1;
            try {
                JSONObject object = new JSONObject(json);
                object.remove("baseObjId");

                String city = mSharedPreferences.getString(Constants.CITY,null);
                String city_id = mSharedPreferences.getString(Constants.CITY_ID,null);
                if ( !TextUtils.isEmpty(city) && !TextUtils.isEmpty(city_id) )
                    object.put("city",city);
                    object.put("city_id",city_id);

                json1 = object.toString();
            } catch (JSONException e) {
                json1 = json;
            }
            Log.d(TAG,"saveBpList:" + json1 );
            OkHttpUtils.postString()
                    .url(Constants.UPLOAD)
                    .mediaType(MediaType.parse("application/json; charset=utf-8"))
                    .content(json1)
                    .build().execute(new StringCallback() {
                @Override
                public void onError(Call call, Exception e, int id) {
                    Log.d(TAG,"saveBpList:"+e.getMessage());
                }
                @Override
                public void onResponse(String response, int id) {
                    Log.d(TAG,"saveBpList:"+response);
                    try {
                        JSONObject jsonObject = new JSONObject(response);
                        int code = jsonObject.getInt("code");
                        if ( 1 == code )
                            bean.delete();
                        else
                            Log.d(TAG,code + ":" + jsonObject.getString("message"));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }


    /**
     * 32位MD5加密
     * @param content -- 待加密内容
     * @return
     */
    public String md5Decode32(String content) {
        byte[] hash;
        try {
            hash = MessageDigest.getInstance("MD5").digest(content.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("NoSuchAlgorithmException",e);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("UnsupportedEncodingException", e);
        }
        //对生成的16字节数组进行补零操作
        StringBuilder hex = new StringBuilder(hash.length * 2);
        for (byte b : hash) {
            if ((b & 0xFF) < 0x10){
                hex.append("0");
            }
            hex.append(Integer.toHexString(b & 0xFF));
        }
        return hex.toString();
    }


    /**
     *
     * @param data
     */
    private void bpDataConvertSave(BPData data){
        DataSupport.deleteAll(XBpData.class);
        XBpData xBpData = new XBpData();
        xBpData.setSystolic( data.getSystolic() );
        xBpData.setDiastolic( data.getDiastolic() );
        xBpData.setPulse( data.getPulse() );
        xBpData.setArrhythmiaFlg( data.getArrhythmiaFlg() );
        xBpData.setBmFlg( data.getBmFlg() );
        xBpData.setCwsFlg( data.getCwsFlg() );
        xBpData.setMeasureTime( data.getMeasureTime() );
        xBpData.setMeasureUser( data.getMeasureUser() );
        boolean result = xBpData.save();
        Log.d(TAG,"xBpData.save:" + result );
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }


    /********************************语音播报************************************/
    private void initSpeecher(){
        mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        // 初始化合成对象
        mTts = SpeechSynthesizer.createSynthesizer(this, mTtsInitListener);
        initParams();
    }


    private void initParams() {
        // 清空参数
        mTts.setParameter(SpeechConstant.PARAMS, null);
        //设置使用本地引擎
        mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
        //设置发音人资源路径
        mTts.setParameter(ResourceUtil.TTS_RES_PATH,getResourcePath());
        //设置发音人
        mTts.setParameter(SpeechConstant.VOICE_NAME,voicerLocal);

        //mTts.setParameter(SpeechConstant.TTS_DATA_NOTIFY,"1");//支持实时音频流抛出，仅在synthesizeToUri条件下支持
        //设置合成语速
        mTts.setParameter(SpeechConstant.SPEED, mSharedPreferences.getString("speed_preference", "50"));
        //设置合成音调
        mTts.setParameter(SpeechConstant.PITCH, mSharedPreferences.getString("pitch_preference", "50"));
        //设置合成音量
        mTts.setParameter(SpeechConstant.VOLUME, mSharedPreferences.getString("volume_preference", "50"));
        //设置播放器音频流类型
        mTts.setParameter(SpeechConstant.STREAM_TYPE, mSharedPreferences.getString("stream_preference", "3"));
        //	mTts.setParameter(SpeechConstant.STREAM_TYPE, AudioManager.STREAM_MUSIC+"");
        // 设置播放合成音频打断音乐播放，默认为true
        mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
        // 设置音频保存路径，保存音频格式支持pcm、wav，设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
        mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");

        mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/tts.wav");

    }

    // 引擎类型
    private String mEngineType = SpeechConstant.TYPE_LOCAL;
    // 默认本地发音人
    public static String voicerLocal="xiaoyan";
    //获取发音人资源路径
    private String getResourcePath(){
        StringBuffer tempBuffer = new StringBuffer();
        String type= "tts";
        if(mEngineType.equals(SpeechConstant.TYPE_XTTS)){
            type="xtts";
        }
        //合成通用资源
        tempBuffer.append(ResourceUtil.generateResourcePath(this, ResourceUtil.RESOURCE_TYPE.assets, type+"/common.jet"));
        tempBuffer.append(";");
        //发音人资源
        tempBuffer.append(ResourceUtil.generateResourcePath(this, ResourceUtil.RESOURCE_TYPE.assets, type + "/" + voicerLocal + ".jet"));

        return tempBuffer.toString();
    }

    /**
     * 初始化监听。
     */
    private InitListener mTtsInitListener = code -> {
        Log.d(TAG, "InitListener init() code = " + code);
        if (code != ErrorCode.SUCCESS) {
            Log.e(TAG,"初始化失败,错误码："+code+",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
        }
    };

    /**
     * 合成回调监听。
     */
    private SynthesizerListener mTtsListener = new SynthesizerListener() {

        @Override
        public void onSpeakBegin() {
            //showTip("开始播放");
            Log.d(TAG,"开始播放："+ System.currentTimeMillis());
        }

        @Override
        public void onSpeakPaused() {
            Log.d(TAG,"暂停播放：");
        }

        @Override
        public void onSpeakResumed() {
            Log.d(TAG,"继续播放");
        }

        @Override
        public void onBufferProgress(int percent, int beginPos, int endPos,
                                     String info) {
            // 合成进度
        }

        @Override
        public void onSpeakProgress(int percent, int beginPos, int endPos) {
            // 播放进度
        }

        @Override
        public void onCompleted(SpeechError error) {
            if (error == null) {
                Log.d(TAG,"播放完成");
            } else if (error != null) {
                Log.d(TAG,error.getPlainDescription(true));
            }
        }

        @Override
        public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
            // 以下代码用于获取与云端的会话id，当业务出错时将会话id提供给技术支持人员，可用于查询会话日志，定位出错原因
            // 若使用本地能力，会话id为null
            if (SpeechEvent.EVENT_SESSION_ID == eventType) {
                String sid = obj.getString(SpeechEvent.KEY_EVENT_AUDIO_URL);
                Log.d(TAG, "session id =" + sid);
            }

            //实时音频流输出参考
			/*if (SpeechEvent.EVENT_TTS_BUFFER == eventType) {
				byte[] buf = obj.getByteArray(SpeechEvent.KEY_EVENT_TTS_BUFFER);
				Log.e("MscSpeechLog", "buf is =" + buf);
			}*/
        }
    };

    /**
     * 唤醒手机屏幕并解锁
     */
    @SuppressWarnings("deprecation")
    public static void wakeUpAndUnlock() {
        // 获取电源管理器对象
        PowerManager pm = (PowerManager) BpApplication.getInstance().getContext()
                .getSystemService(Context.POWER_SERVICE);
        boolean screenOn = pm.isScreenOn();
        if (!screenOn) {
            // 获取PowerManager.WakeLock对象,后面的参数|表示同时传入两个值,最后的是LogCat里用的Tag
            @SuppressLint("InvalidWakeLockTag")
            PowerManager.WakeLock wl = pm.newWakeLock(
                    PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");
            wl.acquire(); // 点亮屏幕
            wl.release(); // 释放
        }
        // 屏幕解锁
        KeyguardManager keyguardManager = (KeyguardManager) BpApplication.getInstance().getContext()
                .getSystemService(KEYGUARD_SERVICE);
        KeyguardManager.KeyguardLock keyguardLock = keyguardManager.newKeyguardLock("unLock");
        // 屏幕锁定
        keyguardLock.reenableKeyguard();
        keyguardLock.disableKeyguard(); // 解锁
    }


}
